package com.kk.xhr.model.service.impl;

import com.kk.xhr.common.pojo.ApplyStatusEnum;
import com.kk.xhr.model.assembler.WorkOvertimeStructKit;
import com.kk.xhr.model.dao.WorkOvertimeDynamicSqlSupport;
import com.kk.xhr.model.dao.WorkOvertimeMapper;
import com.kk.xhr.model.dto.ApplyQueryRequestDTO;
import com.kk.xhr.model.dto.PageDto;
import com.kk.xhr.model.dto.WorkOvertimeDTO;
import com.kk.xhr.model.entity.WorkOvertime;
import com.kk.xhr.model.service.IWorkOvertimeService;
import lombok.RequiredArgsConstructor;
import org.mybatis.dynamic.sql.where.AbstractWhereDSL;
import org.springframework.stereotype.Repository;

import java.util.Optional;
import java.util.stream.Collectors;

import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo;
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualToWhenPresent;
import static org.mybatis.dynamic.sql.SqlBuilder.isGreaterThanOrEqualToWhenPresent;
import static org.mybatis.dynamic.sql.SqlBuilder.isLessThanOrEqualToWhenPresent;

/**
 * 加班服务接口实现
 *
 * @author luokexiong
 * @version 1.0 2021/2/19
 * @since 1.0.0
 */
@Repository
@RequiredArgsConstructor
public class WorkOvertimeServiceImpl implements IWorkOvertimeService {
    private final WorkOvertimeMapper workOvertimeMapper;

    /**
     * {@inheritDoc}
     */
    @Override
    public PageDto<WorkOvertimeDTO> query(ApplyQueryRequestDTO dto) {
        long count = workOvertimeMapper.count(dsl -> applyQueryArgs(dsl.where(), dto));
        if (0 == count) {
            return PageDto.empty();
        }
        return new PageDto<>(count, workOvertimeMapper.select(dsl ->
            applyQueryArgs(dsl.where(), dto)
                .orderBy(WorkOvertimeDynamicSqlSupport.id.descending())
                .limit(dto.getLimit()).offset(dto.getOffset()))
            .stream()
            .map(WorkOvertimeStructKit.INSTANCE::toDto)
            .collect(Collectors.toList()));
    }

    private <T extends AbstractWhereDSL<T>> T applyQueryArgs(T where, ApplyQueryRequestDTO dto) {
        where.and(WorkOvertimeDynamicSqlSupport.userId, isEqualToWhenPresent(dto.getUserId()))
            .and(WorkOvertimeDynamicSqlSupport.reviewerId, isEqualToWhenPresent(dto.getReviewerId()))
            .and(WorkOvertimeDynamicSqlSupport.begin, isGreaterThanOrEqualToWhenPresent(dto.getBegin()))
            .and(WorkOvertimeDynamicSqlSupport.end, isLessThanOrEqualToWhenPresent(dto.getEnd()));
        if (null != dto.getStatus()) {
            where.and(WorkOvertimeDynamicSqlSupport.status, isEqualTo(dto.getStatus().getValue()));
        }
        return where;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean add(WorkOvertimeDTO dto) {
        WorkOvertime entity = new WorkOvertime()
            .withUserId(dto.getUserId())
            .withReviewerId(dto.getReviewerId())
            .withBegin(dto.getBegin())
            .withEnd(dto.getEnd())
            .withDuration(dto.getDuration())
            .withCompensate(dto.getCompensateType().getValue())
            .withType(dto.getType().getValue())
            .withStatus(dto.getStatus().getValue());
        return 1 == workOvertimeMapper.insertSelective(entity);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean modify(Long id, ApplyStatusEnum status) {
        if (null == status) {
            return false;
        }
        return 1 == workOvertimeMapper
            .updateByPrimaryKeySelective(new WorkOvertime().withId(id).withStatus(status.getValue()));
    }

    @Override
    public Optional<WorkOvertimeDTO> query(Long id) {
        return workOvertimeMapper.selectOne(dsl -> dsl
            .where(WorkOvertimeDynamicSqlSupport.id, isEqualTo(id))
            .and(WorkOvertimeDynamicSqlSupport.status, isEqualTo(ApplyStatusEnum.APPLYING.getValue())))
            .map(WorkOvertimeStructKit.INSTANCE::toDto);
    }
}
